﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Trace;
using Microsoft.SqlServer.Management.Common;

namespace OrmSmackdown
{
    public class SQLProfiling
    {
        private TraceServer _tracer;
        public event EventHandler<TraceEventArgs> TraceEvent;

        public SQLProfiling()
        {
            Enabled = true;
        }

        private void WriteTraceLine(string message)
        {

            TraceEvent(this, new TraceEventArgs() {Message = message});
        }

        public void StartTracing()
        {
            _tracer = null;
            try
            {
                string baseDomain = AppDomain.CurrentDomain.BaseDirectory.ToLower();
                baseDomain = baseDomain.Replace(@"bin\debug\", "");

                string traceConfiguration = string.Format(@"{0}SQLTracing\Standard.tdf", baseDomain);

                if (!System.IO.File.Exists(traceConfiguration))
                    traceConfiguration = string.Format(@"{0}\..\..\..\OrmSmackdownTests\SQLTracing\Standard.tdf", AppDomain.CurrentDomain.BaseDirectory);

                if (!System.IO.File.Exists(traceConfiguration))
                    traceConfiguration = string.Format(@"{0}\..\..\SQLTracing\Standard.tdf", AppDomain.CurrentDomain.BaseDirectory);

                if (System.IO.File.Exists(traceConfiguration))
                {
                    WriteTraceLine(String.Format("Using configuration file at:\r\n\t{0}", traceConfiguration));

                    ConnectionInfoBase ci = new SqlConnectionInfo("localhost");
                    ((SqlConnectionInfo)ci).UseIntegratedSecurity = true;

                    _tracer = new TraceServer();
                    _tracer.InitializeAsReader(ci, traceConfiguration);

                    WriteTraceLine("SQL Tracing Available and Initialized");
                }
                else
                    WriteTraceLine(String.Format("Could not find SQL Server Trace Configuration File:\r\n\t{0}", traceConfiguration));
            }
            catch (Exception exc)
            {
                _tracer = null;
                WriteTraceLine("Could not initialize SQL Server Profile Connection.");
                WriteTraceLine("Generated SQL will not be available.");
                WriteTraceLine("Are you targetting x86.");
                WriteTraceLine(String.Format("ERROR: {0}", exc.Message));
            }

            if(_tracer != null)
                new System.Threading.Thread(() => Begin()).Start();
        }

        /// <summary>
        /// More details on how to connect to profiler.
        /// http://blogs.msdn.com/sqlprogrammability/archive/2006/05/26/Receiving-Profiler-Events.aspx
        /// </summary>
        private void Begin()
        {
            while (_tracer != null && _tracer.Read())
            {
                try
                {
                    string traceType = _tracer.GetValue(0).ToString();
                    if ((traceType == "RPC:Completed" || traceType == "SQL:BatchCompleted") && Enabled)
                    {
                        //Reset Connection = new .NET Connection

                        //Console.WriteLine("Event : " + trace["EventClass"]);
                        //Console.WriteLine("SPID  : " + trace["SPID"]);
                        //Console.WriteLine("Login : " + trace["SessionLoginName"]);
                        //Console.WriteLine("Object: " + trace["ObjectName"]);

                        var duration = Convert.ToInt32(_tracer["Duration"]);
                        var reads = Convert.ToInt32(_tracer["Reads"]);
                        var writes = Convert.ToInt32(_tracer["Writes"]);
                        var cpu = Convert.ToInt32(_tracer["CPU"]);

                        WriteTraceLine(_tracer["TextData"].ToString());
                        WriteTraceLine(string.Format("Duration: {0} - Reads: {1} -  Writes: {2} -  CPU: {3}", duration, reads, writes, cpu));
                        WriteTraceLine("======================");
                        WriteTraceLine(string.Empty);
                    }
                }
                catch
                {
                    //does not container text data or text data is null.
                }
            }
        }

        public void StopTracing()
        {
            if (_tracer != null)
            {
                _tracer.Stop();
                _tracer.Close();
                _tracer = null;
            }
        }

        public bool Enabled { get; set; }
    }



    public class TraceEventArgs : EventArgs
    {
        public int Milliseconds { get; set; }
        public string Message { get; set;}
    }
}
